import { Component, OnInit, ViewChild } from '@angular/core';
import { ModalController, PopoverController } from '@ionic/angular';

import { pb } from 'src/pb';
import { EditorComponent } from 'ngx-monaco-editor';
import { isEmpty, map, toNumber, trim } from 'lodash';

import { sleep } from '../utils';
import { LANGUAGES, THEMES } from './const';
import { CallService } from '../call.service';
import { PopoverItem } from '../dialog/popover-options';
import { SelectPathPage } from '../select-path/select-path.page';
import { PopoverComponent } from '../dialog/popover/popover.component';

@Component({
  selector: 'app-editor',
  templateUrl: './editor.page.html',
  styleUrls: ['./editor.page.scss'],
})
export class EditorPage implements OnInit {
  @ViewChild(EditorComponent, { static: true })
  editor: EditorComponent;
  code = '';
  setting: pb.IEditorSettings = {
    theme: 'vs-dark',
    language: 'json',
    formatOnPaste: true,
    fontSize: 26,
  };
  fileName = '';
  readonly themes = THEMES;
  readonly languages = LANGUAGES;
  constructor(
    private callService: CallService,
    private modalCtrl: ModalController,
    private popoverCtrl: PopoverController,
    private win: Window,
  ) { }

  async ngOnInit() {
    const setting = await this.callService.call('get', { def: this.setting }, 'editor');
    if (setting) {
      Object.assign(this.setting, setting);
      this.editor.options = this.setting;
    }
  }

  async onInit() {
    await sleep(500);
    this.win.dispatchEvent(new Event('resize'));
  }

  async selectTheme(event: Event) {
    const items: PopoverItem[] = map(THEMES, (v) => ({
      label: v.value,
      code: v.key,
      icon: v.icon,
      checked: v.key === this.setting.theme,
    }));
    const popover = await this.popoverCtrl.create({
      component: PopoverComponent,
      event,
      translucent: true,
      componentProps: {
        options: {
          title: '主题选择',
          items,
        }
      },
    });

    await popover.present();
    const r = await popover.onDidDismiss();

    if (r && r.data) {
      this.setting = Object.assign(this.setting, { theme: r.data });
      this.save();
      this.editor.options = this.setting;
    }
  }

  async selectLanguage(event: Event) {
    const items: PopoverItem[] = map(LANGUAGES, (v, k) => ({ label: v, code: k, checked: k === this.setting.language }));
    const popover = await this.popoverCtrl.create({
      component: PopoverComponent,
      event,
      translucent: true,
      componentProps: {
        options: {
          title: '语言选择',
          items,
        }
      },
    });

    await popover.present();
    const r = await popover.onDidDismiss();

    if (r && r.data) {
      this.setting.language = r.data;
      this.save();
      this.editor.options = this.setting;
      console.log(r.data);
    }
  }

  async openMenu(event: Event) {
    const items: PopoverItem[] = [
      { label: '选择文件', code: 'select', icon: 'folder-open-outline' },
    ];
    if (this.isText()) {
      items.push(...[
        { label: '文本排序', code: 'sort', icon: 'text' },
        { label: '数值排序', code: 'sortNum', icon: 'bar-chart' },
        { label: '逐行修剪', code: 'trim', icon: 'cut' },
        { label: '删除空行', code: 'clean', icon: 'reader' },
        { label: '去除重复', code: 'unique', icon: 'eye' },
      ]);
    }
    const popover = await this.popoverCtrl.create({
      component: PopoverComponent,
      event,
      translucent: true,
      componentProps: {
        options: {
          title: '更多功能',
          items,
        }
      },
    });
    await popover.present();

    const r = await popover.onDidDismiss();

    if (r && r.data && this[r.data]) {
      this[r.data]();
    }
  }

  isText() {
    return this.setting.language === 'text/plain';
  }

  private sort() {
    this.code = this.code.split('\n')
      .sort()
      .join('\n');
  }

  private sortNum() {
    this.code = this.code.split('\n')
      .sort((a, b) => toNumber(a) - toNumber(b))
      .join('\n');
  }

  private clean() {
    this.code = this.code.split('\n')
      .map(t => trim(t))
      .filter(t => !isEmpty(t))
      .join('\n');
  }

  private unique() {
    const set = new Set<string>();
    this.code = this.code.split('\n')
      .filter(t => {
        if (!set.has(t)) {
          set.add(t);
          return true;
        }
        return false;
      })
      .join('\n');
  }

  private trim() {
    this.code = this.code.split('\n')
      .map(t => trim(t))
      .join('\n');
  }

  private async select() {
    const modal = await this.modalCtrl.create({
      component: SelectPathPage,
      componentProps: { path: '' },
    });
    await modal.present();

    const r = await modal.onDidDismiss();
    if (r.data) {
      const s = await this.callService.call('readFile', { msg: '读取文件', def: `{"msg":"test"}` }, r.data);
      this.code = s;
      this.fileName = r.data;
    }
  }

  private async save() {
    await this.callService.call('set', {}, 'editor', this.setting);
  }
}
